#include <udp_test.h>
#include <iostream>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

using namespace std;


UdpConnection::UdpConnection(unsigned short s_port, int server, string dotted):
    _server_port(s_port), _dotted_decimal_address(dotted) 
{
    _state = -1; 
    _sock_dsc = socket(PF_INET, SOCK_DGRAM, 0);

    if (_sock_dsc < 0) {
        cerr << strerror(errno) << endl;
    } else {
        _state = 0;
        if (server) {
            struct sockaddr_in saddr;
            memset(&saddr, 0, sizeof(saddr));
            if (_dotted_decimal_address.size() > 0)
                saddr.sin_addr.s_addr = inet_addr(_dotted_decimal_address.c_str());
            else
                saddr.sin_addr.s_addr = INADDR_ANY;
            saddr.sin_port = htons(_server_port);
            saddr.sin_family = PF_INET;

            if (bind(_sock_dsc, (const struct sockaddr *)&saddr, sizeof(saddr)) < 0){
                cerr << strerror(errno) << endl;
                close(_sock_dsc);
                _state = -1;
            } 
        }           
    }   
}

UdpConnection::~UdpConnection()
{
    if (_state == 0)
        close(_sock_dsc);
}


int UdpConnection::sendData(const void *buf, int size)
{
    int n;
    struct sockaddr_in to_addr;

    if (!buf || size < 0)
        return -1;
    
    memset(&to_addr, 0, sizeof(to_addr));

    if (_dotted_decimal_address.size() == 0)
        to_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    else
        to_addr.sin_addr.s_addr = inet_addr(_dotted_decimal_address.c_str());

    to_addr.sin_port = htons(_server_port);
    to_addr.sin_family = PF_INET;

    n = sendto(_sock_dsc, buf, size, 0, (const struct sockaddr *)&to_addr, 
            sizeof(to_addr));

    if (n < 0 )  {
        cerr << strerror(errno) << endl;
    }
    return n;
}

int UdpConnection:: reciveData()
{
    int n;
    struct sockaddr_in from_addr;
    socklen_t len = sizeof(from_addr);
    unsigned char buf[2048];

    memset(&from_addr, 0, sizeof(from_addr));

    n = recvfrom(_sock_dsc, buf, 2048, 0, (struct sockaddr *)&from_addr, 
            &len);
    
    if (n < 0) {
        cerr << strerror(errno) << endl;
    } else {
        int i = 0;
        struct in_addr in = {from_addr.sin_addr.s_addr };
        char *p =  inet_ntoa(in);
        cerr << "Recived from "  << p << endl;
        cerr << "Recieved from port "   << ntohs(from_addr.sin_port) << endl;

        while (i < n) {
            if (isprint(buf[i]))
                cerr << buf[i] ;
            else
                cerr << " ";
            i++;
        }

        cerr << "\n";
    }

    return n;
}
